import { Vec3 } from '@/core/types';
import { BlockType } from '@/blocks/types';
import { WorldData, PlayerData, ChunkData, InventoryData, ItemStack, WorldSettings } from './SaveSystem';
import { WorldManager } from './WorldManager';
import { Player } from '@/player/Player';
import { EntityManager } from '@/entities/EntityManager';

export class WorldSerializer {
  private worldManager: WorldManager;
  private chunkSize = 16; // 区块大小

  constructor(worldManager: WorldManager) {
    this.worldManager = worldManager;
  }

  public serializeWorld(player: Player, entityManager: EntityManager): WorldData {
    const worldData: WorldData = {
      version: '1.0.0',
      timestamp: Date.now(),
      playerData: this.serializePlayer(player),
      chunks: this.serializeChunks(),
      entities: entityManager.serializeEntities(),
      gameTime: Date.now(), // 简化版游戏时间
      worldSettings: this.getWorldSettings()
    };

    return worldData;
  }

  public deserializeWorld(worldData: WorldData, player: Player, entityManager: EntityManager): boolean {
    try {
      // 恢复玩家数据
      this.deserializePlayer(worldData.playerData, player);
      
      // 恢复区块数据
      this.deserializeChunks(worldData.chunks);
      
      // 恢复实体数据
      entityManager.deserializeEntities(worldData.entities);
      
      console.log('World deserialized successfully');
      return true;
    } catch (error) {
      console.error('Failed to deserialize world:', error);
      return false;
    }
  }

  private serializePlayer(player: Player): PlayerData {
    const inventory = player.getInventory();
    
    return {
      position: player.getPosition(),
      rotation: { x: 0, y: 0 }, // 简化版，实际需要从player获取
      health: player.getHealth(),
      hunger: player.getHunger(),
      inventory: this.serializeInventory(inventory),
      gameMode: 'survival' // 简化版
    };
  }

  private deserializePlayer(playerData: PlayerData, player: Player): void {
    // 恢复玩家位置
    player.setPosition(playerData.position);
    
    // 恢复玩家状态
    if (playerData.health < player.getHealth()) {
      player.takeDamage(player.getHealth() - playerData.health);
    } else if (playerData.health > player.getHealth()) {
      player.heal(playerData.health - player.getHealth());
    }
    
    // 恢复物品栏
    this.deserializeInventory(playerData.inventory, player.getInventory());
  }

  private serializeInventory(inventory: any): InventoryData {
    const items: ItemStack[] = [];
    
    // 序列化物品栏中的所有物品
    for (let i = 0; i < 36; i++) { // 假设有36个槽位
      const item = inventory.getItem(i);
      if (item && item.count > 0) {
        items.push({
          type: item.type,
          count: item.count,
          slot: i
        });
      }
    }
    
    return {
      items,
      selectedSlot: inventory.getSelectedSlot()
    };
  }

  private deserializeInventory(inventoryData: InventoryData, inventory: any): void {
    // 清空现有物品栏
    inventory.clear();
    
    // 恢复物品
    for (const itemStack of inventoryData.items) {
      inventory.setItem(itemStack.slot, itemStack.type, itemStack.count);
    }
    
    // 恢复选中的槽位
    inventory.setSelectedSlot(inventoryData.selectedSlot);
  }

  private serializeChunks(): ChunkData[] {
    const chunks: ChunkData[] = [];
    
    // 获取所有已加载的区块
    const loadedChunks = this.worldManager.getLoadedChunks();
    
    for (const chunk of loadedChunks) {
      const chunkData: ChunkData = {
        x: chunk.position.x,
        z: chunk.position.z,
        blocks: this.serializeChunkBlocks(chunk),
        lastModified: Date.now()
      };
      
      chunks.push(chunkData);
    }
    
    return chunks;
  }

  private serializeChunkBlocks(chunk: any): BlockType[][][] {
    const blocks: BlockType[][][] = [];
    
    // 序列化区块中的所有方块
    for (let x = 0; x < this.chunkSize; x++) {
      blocks[x] = [];
      for (let y = 0; y < 64; y++) { // 假设世界高度为64
        blocks[x][y] = [];
        for (let z = 0; z < this.chunkSize; z++) {
          const worldX = chunk.x * this.chunkSize + x;
          const worldZ = chunk.z * this.chunkSize + z;
          const blockType = this.worldManager.getBlock({ x: worldX, y, z: worldZ });
          blocks[x][y][z] = blockType;
        }
      }
    }
    
    return blocks;
  }

  private deserializeChunks(chunksData: ChunkData[]): void {
    for (const chunkData of chunksData) {
      this.deserializeChunk(chunkData);
    }
  }

  private deserializeChunk(chunkData: ChunkData): void {
    // 恢复区块中的所有方块
    for (let x = 0; x < this.chunkSize; x++) {
      for (let y = 0; y < 64; y++) {
        for (let z = 0; z < this.chunkSize; z++) {
          if (chunkData.blocks[x] && chunkData.blocks[x][y] && chunkData.blocks[x][y][z] !== undefined) {
            const worldX = chunkData.x * this.chunkSize + x;
            const worldZ = chunkData.z * this.chunkSize + z;
            const blockType = chunkData.blocks[x][y][z];
            
            this.worldManager.setBlock({ x: worldX, y, z: worldZ }, blockType);
          }
        }
      }
    }
  }

  private getWorldSettings(): WorldSettings {
    return {
      seed: 12345, // 简化版固定种子
      gameMode: 'survival',
      difficulty: 'normal',
      allowCheats: false
    };
  }

  public compressChunkData(chunkData: ChunkData): ChunkData {
    // 简化的区块数据压缩
    // 在实际应用中可以实现更复杂的压缩算法，如RLE（行程长度编码）
    
    // 这里只是一个占位符，实际压缩逻辑可以后续实现
    return chunkData;
  }

  public decompressChunkData(compressedChunkData: ChunkData): ChunkData {
    // 简化的区块数据解压
    return compressedChunkData;
  }

  public validateChunkData(chunkData: ChunkData): boolean {
    // 验证区块数据的完整性
    if (!chunkData || typeof chunkData !== 'object') {
      return false;
    }
    
    if (typeof chunkData.x !== 'number' || typeof chunkData.z !== 'number') {
      return false;
    }
    
    if (!Array.isArray(chunkData.blocks)) {
      return false;
    }
    
    // 检查区块数据的维度
    if (chunkData.blocks.length !== this.chunkSize) {
      return false;
    }
    
    return true;
  }

  public getSerializationStats(worldData: WorldData): any {
    const stats = {
      totalSize: JSON.stringify(worldData).length,
      playerDataSize: JSON.stringify(worldData.playerData).length,
      chunksDataSize: JSON.stringify(worldData.chunks).length,
      entitiesDataSize: JSON.stringify(worldData.entities).length,
      chunkCount: worldData.chunks.length,
      entityCount: worldData.entities.length,
      inventoryItemCount: worldData.playerData.inventory.items.length
    };
    
    return stats;
  }
}